package com.soft.bams.service;

import com.soft.bams.dao.FileDao;
import com.soft.bams.dao.IDao;
import com.soft.bams.dao.ListDao;
import com.soft.bams.entity.*;
import com.soft.bams.exception.*;
import com.soft.bams.server.ServerTasker;
import com.soft.bams.vo.RankVO;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @author yzg
 * @desc TODO
 * @date 2025/4/17
 */
public class Bank {
    private static Bank instance = new Bank();
    private IDao<Account, List<Account>> dao;

    private Bank() {
        this.dao = new FileDao();

    }

    public static Bank getInstance() {
        return instance;
    }


    public IDao<Account, List<Account>> getDao() {
        return dao;
    }

    // 用户开户
    public Account register(String password, String rePassword, String name,
                            String personID, String email, int type) throws RegisterException, TypeException {

        if(password==null || rePassword==null || password.equals("") || rePassword.equals("")){
            throw new RegisterException("密码不能为空");
            //return null;
        }
        if (!password.equals(rePassword)) {
            throw new RegisterException("两次输入密码不一致");
            //return null;
        }

        Long id = dao.createId();
        if(id == -1L){
            throw new RegisterException("开户失败");
        }
        Account account;
        switch (type) {
            case 0: // 储蓄账户
                account = new SavingAccount(id, password, name, personID, email, 0);
                break;
            case 1: // 信用账户
                account = new CreditAccount(id, password, name, personID, email, 0, 1000); // 默认透支额度1000
                break;
            case 2: // 可贷款储蓄账户
                account = new LoanSavingAccount(id,password,name,personID,email,0);
                break;
            case 3: // 可贷款信用账户
                account = new LoanCreditAccount(id,password,name,personID,email,0,1000);  // 默认透支额度1000
                break;
            default:
                throw new TypeException("不支持的账户类型");
                //return null;
        }

        dao.insert(account);
        return account;
    }

    // 用户登录
    public Account login(Long id, String password) throws LoginException {
        if(id == null || password == null || password.equals("")){
            throw new LoginException("用户ID和密码不能为空");
            //return null;
        }
        return dao.selectOne(id, password);
    }

    // 用户存款
    public Account deposit(Long id, double money) throws NotFoundException {
        if(id == null){
            throw new NotFoundException("账户ID不能为空");
            //return null;
        }
        Account account = dao.selectOne(id); 
        if (account != null) {
            account.deposit(money);
            dao.update(account);
        }else {
            throw new NotFoundException("账户ID不存在");
        }
        return account;
        //return null;

    }

    // 用户取款
    public Account withdraw(Long id, String password, double money) throws BalanceNotEnoughException, NotFoundException {
        if(id == null || password == null || password.equals("")){
            throw new NotFoundException("账户ID和密码不能为空");
            //return null;
        }
        Account account = dao.selectOne(id, password);
        if (account != null) {
            account.withdraw(money);
            dao.update(account);
        }else {
            throw new NotFoundException("账户ID与密码不匹配");
        }
        return account;
        //return null;
    }

    // 设置透支额度
    public Account updateCeiling(Long id, String password, double money) throws NotFoundException, TypeException {
        if(id == null || password == null || password.equals("")){
            throw new NotFoundException("账户ID和密码不能为空");
            //return null;
        }
        Account account = dao.selectOne(id, password);
        if(account != null){
            if (account instanceof CreditAccount) {
                ((CreditAccount) account).setCeiling(money);
                dao.update(account);
            }else {
                throw new TypeException("非信用账户，无法设置透支额度");
            }
        }else {
            throw new NotFoundException("当前账户ID和密码不匹配!");
        }
        return account;
        //System.out.println("非信用账户，无法设置透支额度");
        //return null;
    }

    // 转账功能
    public boolean transfer(Long from, String passwordFrom, Long to, double money) throws BalanceNotEnoughException, NotFoundException {
        if(from == null || passwordFrom == null || passwordFrom.equals("") || to == null){
            throw new NotFoundException("转出账户或转入账户不能为空");
            //return false;
        }
        Account fromAccount = dao.selectOne(from, passwordFrom);
        Account toAccount = dao.selectOne(to);

        if (fromAccount == null || toAccount == null) {
            throw new NotFoundException("账户不存在或密码错误");
            //return false;
        }

        // 记录转出前余额和透支额度
        double originalBalance = fromAccount.getBalance();
        double originalCeiling = 0;
        if (fromAccount instanceof CreditAccount) {
            originalCeiling = ((CreditAccount) fromAccount).getCeiling();
        }

        // 执行转出操作
        Account afterWithdraw = fromAccount.withdraw(money);

        // 检查转出是否成功
        boolean withdrawSuccess;

        if (fromAccount instanceof CreditAccount) {
            CreditAccount creditAccount = (CreditAccount) fromAccount;
            withdrawSuccess = !(afterWithdraw.getBalance() == originalBalance &&
                    creditAccount.getCeiling() == originalCeiling);
        } else {
            withdrawSuccess = afterWithdraw.getBalance() != originalBalance;
        }

        if (!withdrawSuccess) {
            System.out.println("转出失败");
            return false;
        }


        // 向转入账户存款
        toAccount.deposit(money);
        dao.update(toAccount);
        dao.update(fromAccount);


        return true;

    }

    // 新增贷款方法
    public Account requestLoan(Long id, double money) throws NotFoundException, TypeException, LoanException {
        if(id == null){
            throw new NotFoundException("账户ID不能为空");
            //return null;
        }
        Account account = dao.selectOne(id);
        if (account != null) {
            if (account instanceof Loanable) {
                ((Loanable) account).requestLoan(money);
                dao.update(account);
            }else {
                throw new TypeException("该账户不支持贷款功能");
            }

        }else {
            throw new NotFoundException("账户ID不存在!");
        }
        return account;
        //System.out.println("该账户不支持贷款功能");
        //return null;
    }

    // 新增还贷方法
    public Account payLoan(Long id, double money) throws BalanceNotEnoughException, NotFoundException, TypeException {
        if(id == null){
            throw new NotFoundException("账户ID不能为空");
            //return null;
        }
        Account account = dao.selectOne(id);
        if (account != null) {
            if (account instanceof Loanable) {
                ((Loanable) account).payLoan(money);
                dao.update(account);
            }else {
                throw new TypeException("该账户不支持贷款功能");
            }

        }else {
            throw new NotFoundException("账户ID不存在！");
        }
        return account;
        //System.out.println("该账户不支持贷款功能");
        //return null;
    }

    // 新增统计所有账户贷款总额方法
    public long getTotalLoanAmount() {
        long total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc instanceof LoanSavingAccount) {
                total += ((LoanSavingAccount) acc).getLoanAmount();
            } else if (acc instanceof LoanCreditAccount) {
                total += ((LoanCreditAccount) acc).getLoanAmount();
            }
        }
        return total;
    }

    // 统计所有账户余额总数
    public double getTotalBalance() {
        double total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc != null) {
                total += acc.getBalance();
            }
        }
        return total;
    }

    // 统计所有信用账户透支额度总数
    public double getTotalCeiling() {
        double total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc instanceof CreditAccount) {
                total += ((CreditAccount) acc).getCeiling();
            }
        }
        return total;
    }

    //统计所有用户总资产排名
    public TreeSet<RankVO> userAssetRank() {
        List<Account> accounts = dao.selectAll();

        TreeSet<RankVO> userRank = new TreeSet<>();

        Map<String, RankVO> tempMap = new HashMap<>();

        for (Account account : accounts) {
            String personId = account.getPersonId();
            RankVO rankVO = tempMap.get(personId);

            if (rankVO == null) {
                rankVO = new RankVO(personId, account.getName(), account.getBalance());
                userRank.add(rankVO);
                tempMap.put(personId, rankVO);
            } else {
                userRank.remove(rankVO);
                rankVO.addAsset(account.getBalance());
                userRank.add(rankVO);
            }
        }

        System.out.println("---------- 用户总资产排名 --------");

        for (RankVO rankVO : userRank) {
            System.out.println(rankVO);
        }

        return userRank;
    }

    public Set<Map.Entry<Long,String>> getAccountsIpInfo(){
        return ServerTasker.getAccountsIp().entrySet();
    }
}